echo DOM= $DOM
-VIF=`cat /proc/xeno/dom$DOM/vif`
-
-echo VIF= $VIF
-
-$VIFINIT $VIF $IP
+$VIFINIT $DOM 0 $IP
#
# Usage is:
#
-# vifinit [vif id] [dotted decimal ip address]
+# vifinit [vif dom] [vif idx] [dotted decimal ip address]
#
-if [ $# -ne 2 ] ;
+if [ $# -ne 3 ] ;
then
- echo "usage: vifinit [vif id] [dotted decimal ip address]"
+ echo "usage: vifinit [vif dom] [vif idx] [dotted decimal ip address]"
exit
fi
#outbound rule:
-echo "ADD ACCEPT srcaddr=$2 srcaddrmask=255.255.255.255 srcint=$1 dstint=-1 proto=any" > /proc/vfr
+echo "ADD ACCEPT srcaddr=$3 srcaddrmask=255.255.255.255 srcdom=$1 srcidx=$2 dst=PHYS proto=any" > /proc/vfr
#inbound rule:
-echo "ADD ACCEPT dstaddr=$2 dstaddrmask=255.255.255.255 srcint=-4 dstint=$1 proto=any" > /proc/vfr
+echo "ADD ACCEPT dstaddr=$3 dstaddrmask=255.255.255.255 src=ANY dstdom=$1 dstidx=$2 proto=any" > /proc/vfr
#----] done.
#include <asm/pgalloc.h>
#include <asm/hardirq.h>
#include <asm/apic.h>
+#include <xeno/mm.h>
#include <asm/timex.h>
#include <xeno/ac_timer.h>
* (C) Copyright 1995 1996 Linus Torvalds
*/
-//#include <linux/vmalloc.h>
+#include <xeno/config.h>
+#include <xeno/lib.h>
+#include <xeno/mm.h>
#include <asm/io.h>
#include <asm/pgalloc.h>
#include <asm/page.h>
#include <xeno/init.h>
#include <xeno/interrupt.h>
#include <xeno/irq.h>
+#include <xeno/mm.h>
+#include <xeno/slab.h>
#include <asm/pgalloc.h>
#include <asm/mc146818rtc.h>
#include <asm/smpboot.h>
#include <xeno/sched.h>
#include <xeno/lib.h>
#include <xeno/errno.h>
+#include <xeno/mm.h>
#include <asm/ptrace.h>
#include <xeno/delay.h>
#include <xeno/spinlock.h>
#include <xeno/config.h>
#include <xeno/types.h>
#include <xeno/lib.h>
+#include <xeno/mm.h>
#include <xeno/dom0_ops.h>
#include <xeno/sched.h>
#include <xeno/event.h>
#include <xeno/config.h>
#include <xeno/types.h>
#include <xeno/lib.h>
+#include <xeno/mm.h>
#include <xeno/dom_mem_ops.h>
#include <xeno/sched.h>
#include <xeno/event.h>
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED)
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
+/* Both these structures are protected by the tasklist_lock. */
rwlock_t tasklist_lock __cacheline_aligned = RW_LOCK_UNLOCKED;
-
-#define TASK_HASH_SIZE 256
-#define TASK_HASH(_id) ((_id)&(TASK_HASH_SIZE-1))
-static struct task_struct *task_hash[TASK_HASH_SIZE];
+struct task_struct *task_hash[TASK_HASH_SIZE];
/*
* create a new domain
ethh->h_proto = htons(ETH_P_IP);
skb->mac.ethernet= (struct ethhdr *)ethh;
- /* Keep the net rule tables happy. */
- skb->src_vif = VIF_PHYSICAL_INTERFACE;
- skb->dst_vif = 0;
-
unmap_domain_mem(skb_data);
(void)netif_rx(skb);
#include <asm/domain_page.h>
#include <asm/io.h>
-/* vif globals
- * sys_vif_list is a lookup table for vifs, used in packet forwarding.
- * it will be replaced later by something a little more flexible.
- */
-
-int sys_vif_count; /* global vif count */
-net_vif_t *sys_vif_list[MAX_SYSTEM_VIFS]; /* global vif array */
net_rule_ent_t *net_rule_list; /* global list of rules */
kmem_cache_t *net_vif_cache;
kmem_cache_t *net_rule_cache;
static rwlock_t net_rule_lock = RW_LOCK_UNLOCKED; /* rule mutex */
-rwlock_t sys_vif_lock = RW_LOCK_UNLOCKED; /* vif mutex */
-
void print_net_rule_list();
/* ----[ VIF Functions ]----------------------------------------------------*/
+
+net_vif_t *find_vif_by_id(unsigned long id)
+{
+ struct task_struct *p;
+ net_vif_t *vif = NULL;
+ unsigned long flags, dom = id>>VIF_DOMAIN_SHIFT;
+
+ read_lock_irqsave(&tasklist_lock, flags);
+ p = task_hash[TASK_HASH(dom)];
+ while ( p != NULL )
+ {
+ if ( p->domain == dom )
+ {
+ vif = p->net_vif_list[id&VIF_INDEX_MASK];
+ if ( vif != NULL ) get_vif(vif);
+ break;
+ }
+ p = p->next_hash;
+ }
+ read_unlock_irqrestore(&tasklist_lock, flags);
+
+ return vif;
+}
+
+
/* create_net_vif - Create a new vif and append it to the specified domain.
*
* the domain is examined to determine how many vifs currently are allocated
* global list.
*
*/
-
net_vif_t *create_net_vif(int domain)
{
int dom_vif_idx;
if ( !(p = find_domain_by_id(domain)) )
return NULL;
+ write_lock_irqsave(&tasklist_lock, flags);
+
for ( dom_vif_idx = 0; dom_vif_idx < MAX_DOMAIN_VIFS; dom_vif_idx++ )
if ( p->net_vif_list[dom_vif_idx] == NULL ) break;
if ( dom_vif_idx == MAX_DOMAIN_VIFS )
new_vif->shared_rings = new_ring;
new_vif->shared_idxs = &p->shared_info->net_idx[dom_vif_idx];
new_vif->domain = p;
+ new_vif->idx = dom_vif_idx;
new_vif->list.next = NULL;
spin_lock_init(&new_vif->rx_lock);
spin_lock_init(&new_vif->tx_lock);
p->net_vif_list[dom_vif_idx] = new_vif;
-
- write_lock_irqsave(&sys_vif_lock, flags);
- new_vif->id = sys_vif_count;
- sys_vif_list[sys_vif_count++] = new_vif;
- write_unlock_irqrestore(&sys_vif_lock, flags);
+ write_unlock_irqrestore(&tasklist_lock, flags);
return new_vif;
fail:
+ write_unlock_irqrestore(&tasklist_lock, flags);
if ( new_vif != NULL )
kmem_cache_free(net_vif_cache, new_vif);
if ( p != NULL )
void unlink_net_vif(net_vif_t *vif)
{
unsigned long flags;
- int i;
if ( vif == NULL )
return;
- for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
- if ( vif->domain->net_vif_list[i] == vif )
- vif->domain->net_vif_list[i] = NULL;
-
- write_lock_irqsave(&sys_vif_lock, flags);
- sys_vif_list[vif->id] = NULL;
- write_unlock_irqrestore(&sys_vif_lock, flags);
-
+ write_lock_irqsave(&tasklist_lock, flags);
+ vif->domain->net_vif_list[vif->idx] = NULL;
+ write_unlock_irqrestore(&tasklist_lock, flags);
+
put_vif(vif);
}
-/* vif_query - Call from the proc file system to get a list of vifs
- * assigned to a particular domain.
+/* vif_query - Call from the proc file system to get a list of indexes
+ * in use by a particular domain.
*/
-
void vif_query(vif_query_t *vq)
{
net_vif_t *vif;
struct task_struct *p;
- unsigned long flags;
char buf[128];
int i;
*buf = '\0';
- read_lock_irqsave(&sys_vif_lock, flags);
- for ( i = 0; i < MAX_SYSTEM_VIFS; i++ )
+ for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
{
- vif = sys_vif_list[i];
- if ( (vif == NULL) || (vif->domain != p) ) continue;
- sprintf(buf + strlen(buf), "%d\n", vif->id);
+ vif = p->net_vif_list[i];
+ if ( vif == NULL ) continue;
+ sprintf(buf + strlen(buf), "%d\n", i);
}
- read_unlock_irqrestore(&sys_vif_lock, flags);
copy_to_user(vq->buf, buf, strlen(buf) + 1);
net_rule_ent_t *new_ent;
if ( (new_ent = kmem_cache_alloc(net_rule_cache, GFP_KERNEL)) == NULL )
- {
return -ENOMEM;
- }
memcpy(&new_ent->r, rule, sizeof(net_rule_t));
* ip address to the specified vif. It's used to set up domain zero.
*/
-void add_default_net_rule(int vif_id, u32 ipaddr)
+void add_default_net_rule(unsigned long vif_id, u32 ipaddr)
{
net_rule_t new_rule;
memset(&new_rule, 0, sizeof(net_rule_t));
new_rule.src_addr = ipaddr;
new_rule.src_addr_mask = 0xffffffff;
- new_rule.src_interface = vif_id;
- new_rule.dst_interface = VIF_PHYSICAL_INTERFACE;
+ new_rule.src_vif = vif_id;
+ new_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
new_rule.action = NETWORK_ACTION_ACCEPT;
new_rule.proto = NETWORK_PROTO_ANY;
add_net_rule(&new_rule);
memset(&new_rule, 0, sizeof(net_rule_t));
new_rule.dst_addr = ipaddr;
new_rule.dst_addr_mask = 0xffffffff;
- new_rule.src_interface = VIF_ANY_INTERFACE;
- new_rule.dst_interface = vif_id;
+ new_rule.src_vif = VIF_ANY_INTERFACE;
+ new_rule.dst_vif = vif_id;
new_rule.action = NETWORK_ACTION_ACCEPT;
new_rule.proto = NETWORK_PROTO_ANY;
add_net_rule(&new_rule);
printk("=] dst_port : %u\n", r->dst_port);
printk("=] dst_port_mask : %u\n", r->dst_port_mask);
printk("=] dst_proto : %u\n", r->proto);
- printk("=] src_interface : %d\n", r->src_interface);
- printk("=] dst_interface : %d\n", r->dst_interface);
+ switch ( r->src_vif )
+ {
+ case VIF_PHYSICAL_INTERFACE:
+ printk("=] src_dom/idx : PHYSICAL\n");
+ break;
+ case VIF_ANY_INTERFACE:
+ printk("=] src_dom/idx : ANY\n");
+ break;
+ default:
+ printk("=] src_dom/idx : %lu/%lu\n",
+ r->src_vif>>VIF_DOMAIN_SHIFT, r->src_vif&VIF_INDEX_MASK);
+ break;
+ }
+ switch ( r->dst_vif )
+ {
+ case VIF_PHYSICAL_INTERFACE:
+ printk("=] dst_dom/idx : PHYSICAL\n");
+ break;
+ case VIF_ANY_INTERFACE:
+ printk("=] dst_dom/idx : ANY\n");
+ break;
+ default:
+ printk("=] dst_dom/idx : %lu/%lu\n",
+ r->dst_vif>>VIF_DOMAIN_SHIFT, r->dst_vif&VIF_INDEX_MASK);
+ break;
+ }
printk("=] action : %u\n", r->action);
}
* Apply the rules to this skbuff and return the vif id that it is bound for.
* If there is no match, VIF_DROP is returned.
*/
-int net_find_rule(u8 nproto, u8 tproto, u32 src_addr, u32 dst_addr,
- u16 src_port, u16 dst_port, int src_vif)
+static net_vif_t *net_find_rule(u8 nproto, u8 tproto, u32 src_addr,
+ u32 dst_addr, u16 src_port,
+ u16 dst_port, unsigned long src_vif)
{
net_rule_ent_t *ent;
- int dest = VIF_DROP;
-
+ unsigned long dest = VIF_UNKNOWN_INTERFACE;
+
read_lock(&net_rule_lock);
ent = net_rule_list;
while ( ent != NULL )
{
- if ( ((ent->r.src_interface == src_vif)
- || (ent->r.src_interface == VIF_ANY_INTERFACE)) &&
+ if ( ((ent->r.src_vif == src_vif)
+ || (ent->r.src_vif == VIF_ANY_INTERFACE)) &&
(!((ent->r.src_addr ^ src_addr) & ent->r.src_addr_mask )) &&
(!((ent->r.dst_addr ^ dst_addr) & ent->r.dst_addr_mask )) &&
/*
* XXX FFS! We keep going to find the "best" rule. Where best
* corresponds to vaguely sane routing of a packet. We need a less
- * shafted model for aour "virtual firewall/router" methinks!
+ * shafted model for our "virtual firewall/router" methinks!
*/
- if ( dest < 0 )
- dest = ent->r.dst_interface;
- if ( dest >= 0 )
+ if ( (dest & VIF_DOMAIN_MASK) == VIF_SPECIAL )
+ dest = ent->r.dst_vif;
+ if ( (dest & VIF_DOMAIN_MASK) != VIF_SPECIAL )
break;
}
ent = ent->next;
}
read_unlock(&net_rule_lock);
- return dest;
+
+ if ( dest == VIF_PHYSICAL_INTERFACE )
+ return VIF_PHYS;
+ else if ( (dest & VIF_DOMAIN_MASK) == VIF_SPECIAL )
+ return VIF_DROP;
+ else
+ return find_vif_by_id(dest);
}
/* net_get_target_vif - Find the vif that the given sk_buff is bound for.
* based on the packet type. it then calls net_find_rule to scan the rule
* list.
*/
-
-#define net_get_target_vif(skb) __net_get_target_vif(skb->data, skb->len, skb->src_vif)
-
-int __net_get_target_vif(u8 *data, unsigned int len, int src_vif)
+net_vif_t *net_get_target_vif(u8 *data, unsigned int len, net_vif_t *src_vif)
{
- int target = VIF_DROP;
+ net_vif_t *target = VIF_DROP;
u8 *h_raw, *nh_raw;
-
+ unsigned long src_vif_val = VIF_PHYSICAL_INTERFACE;
+
+ if ( src_vif != VIF_PHYS )
+ src_vif_val = (src_vif->domain->domain<<VIF_DOMAIN_SHIFT) |
+ src_vif->idx;
+
if ( len < ETH_HLEN ) goto drop;
nh_raw = data + ETH_HLEN;
if ( len < (ETH_HLEN + 28) ) goto drop;
target = net_find_rule((u8)ETH_P_ARP, 0, ntohl(*(u32 *)(nh_raw + 14)),
ntohl(*(u32 *)(nh_raw + 24)), 0, 0,
- src_vif);
+ src_vif_val);
break;
case ETH_P_IP:
if ( len < (ETH_HLEN + 20) ) goto drop;
h_raw = data + ((*(unsigned char *)(nh_raw)) & 0x0f) * 4;
-
- /* XXX For now, we ignore ports. */
-#if 0
- target = net_find_rule((u8)ETH_P_IP, *(u8 *)(nh_raw + 9),
- ntohl(*(u32 *)(nh_raw + 12)),
- ntohl(*(u32 *)(nh_raw + 16)),
- ntohs(*(u16 *)(h_raw)),
- ntohs(*(u16 *)(h_raw + 2)),
- src_vif);
-#else
+ /* NB. For now we ignore ports. */
target = net_find_rule((u8)ETH_P_IP, *(u8 *)(data + 9),
ntohl(*(u32 *)(nh_raw + 12)),
ntohl(*(u32 *)(nh_raw + 16)),
0,
0,
- src_vif);
-#endif
+ src_vif_val);
+ break;
}
return target;
drop:
- printk("VIF%d: pkt to drop!\n", src_vif);
+ printk("VIF%lu/%lu: pkt to drop!\n",
+ src_vif_val>>VIF_DOMAIN_SHIFT, src_vif_val&VIF_INDEX_MASK);
return VIF_DROP;
}
void __init net_init (void)
{
- sys_vif_count = 0;
- memset(sys_vif_list, 0, sizeof(sys_vif_list));
net_rule_list = NULL;
net_vif_cache = kmem_cache_create("net_vif_cache", sizeof(net_vif_t),
0, SLAB_HWCACHE_ALIGN, NULL, NULL);
#include <xeno/time.h>
#include <xeno/ac_timer.h>
#include <xeno/interrupt.h>
-
+#include <xeno/timer.h>
#include <xeno/perfc.h>
#include <xeno/keyhandler.h>
#include <xeno/interrupt.h>
#include <xeno/segment.h>
+#include <xeno/slab.h>
#if 0
#define DPRINTK(_f, _a...) printk( _f , ## _a )
#define _SCSI_H
#include <xeno/config.h> /* for CONFIG_SCSI_LOGGING */
-/*#include <xeno/devfs_fs_kernel.h>*/
+#include <xeno/timer.h>
/*#include <xeno/proc_fs.h>*/
/*
u16 src_port_mask;
u16 dst_port_mask;
u16 proto;
-
- int src_interface;
- int dst_interface;
+ unsigned long src_vif;
+ unsigned long dst_vif;
u16 action;
} net_rule_t;
+#define VIF_DOMAIN_MASK 0xfffff000UL
+#define VIF_DOMAIN_SHIFT 12
+#define VIF_INDEX_MASK 0x00000fffUL
+#define VIF_INDEX_SHIFT 0
+
+/* These are specified in the index if the dom is SPECIAL. */
+#define VIF_SPECIAL 0xfffff000UL
+#define VIF_UNKNOWN_INTERFACE (VIF_SPECIAL | 0)
+#define VIF_PHYSICAL_INTERFACE (VIF_SPECIAL | 1)
+#define VIF_ANY_INTERFACE (VIF_SPECIAL | 2)
+
typedef struct vif_query_st
{
unsigned int domain;
#include <xeno/list.h>
#include <xeno/kdev_t.h>
#include <xeno/sched.h>
+#include <xeno/mm.h>
/* Some defines from fs.h that may actually be useful to the blkdev layer. */
#define READ 0
#include <xeno/hdsmart.h>
#include <xeno/major.h>
#include <xeno/blkdev.h>
-/*#include <xeno/proc_fs.h>*/
+#include <xeno/timer.h>
/*#include <xeno/devfs_fs_kernel.h>*/
#include <asm/hdreg.h>
int idle_cpu(int cpu); /* Is CPU 'cpu' idle right now? */
void cpu_idle(void); /* Idle loop. */
+/* This hash table is protected by the tasklist_lock. */
+#define TASK_HASH_SIZE 256
+#define TASK_HASH(_id) ((_id)&(TASK_HASH_SIZE-1))
+struct task_struct *task_hash[TASK_HASH_SIZE];
+
#define REMOVE_LINKS(p) do { \
(p)->next_task->prev_task = (p)->prev_task; \
(p)->prev_task->next_task = (p)->next_task; \
#include <asm/types.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
-
-/* vif special values */
-#define VIF_PHYSICAL_INTERFACE -1
-#define VIF_UNKNOWN_INTERFACE -2
-#define VIF_DROP -3
-#define VIF_ANY_INTERFACE -4
+#include <xeno/vif.h>
/* skb_type values */
#define SKB_NORMAL 0 /* A Linux-style skbuff: no strangeness */
void (*destructor)(struct sk_buff *); /* Destruct function */
struct pfn_info *pf; /* record of physical pf address for freeing */
- int src_vif; /* vif we came from */
- int dst_vif; /* vif we are bound for */
+ net_vif_t *src_vif; /* vif we came from */
+ net_vif_t *dst_vif; /* vif we are bound for */
struct skb_shared_info shinfo; /* shared info is no longer shared in Xen. */
};
* Copyright (c) 2002-2003, A K Warfield and K A Fraser
*/
+#ifndef __XENO_VIF_H__
+#define __XENO_VIF_H__
+
/* virtual network interface struct and associated defines. */
/* net_vif_st is the larger struct that describes a virtual network interface
* it contains a pointer to the net_ring_t structure that needs to be on a
*/
#include <hypervisor-ifs/network.h>
-#include <xeno/skbuff.h>
/*
* shadow ring structures are used to protect the descriptors from
unsigned int tx_resp_prod; /* private version of shared variable */
/* Miscellaneous private stuff. */
- int id;
struct task_struct *domain;
+ unsigned int idx; /* index within domain */
struct list_head list; /* scheduling list */
atomic_t refcnt;
spinlock_t rx_lock, tx_lock;
if ( atomic_dec_and_test(&(_v)->refcnt) ) destroy_net_vif(_v); \
} while (0) \
-/* VIF-related defines. */
-#define MAX_SYSTEM_VIFS 256
-
-/* vif globals */
-extern int sys_vif_count;
-extern net_vif_t *sys_vif_list[];
-extern rwlock_t sys_vif_lock; /* protects the sys_vif_list */
-
/* vif prototypes */
net_vif_t *create_net_vif(int domain);
void destroy_net_vif(net_vif_t *vif);
void unlink_net_vif(net_vif_t *vif);
-void add_default_net_rule(int vif_id, u32 ipaddr);
-int __net_get_target_vif(u8 *data, unsigned int len, int src_vif);
-void add_default_net_rule(int vif_id, u32 ipaddr);
-
-#define net_get_target_vif(skb) __net_get_target_vif(skb->data, skb->len, skb->src_vif)
-/* status fields per-descriptor:
+void add_default_net_rule(unsigned long vif_id, u32 ipaddr);
+net_vif_t *net_get_target_vif(u8 *data, unsigned int len, net_vif_t *src_vif);
+net_vif_t *find_vif_by_id(unsigned long id);
+
+/*
+ * Return values from net_get_target_vif:
+ * VIF_PHYS -- Send to physical NIC
+ * VIF_DROP -- Drop this packet
+ * others -- Send to specified VIF (reference held on return)
*/
+#define VIF_PHYS ((net_vif_t *)0)
+#define VIF_DROP ((net_vif_t *)1)
+#endif /* __XENO_VIF_H__ */
{
int offset, this_cpu = smp_processor_id();
unsigned long flags;
- net_vif_t *vif;
local_irq_save(flags);
netdev_rx_stat[this_cpu].total++;
- if ( skb->src_vif == VIF_UNKNOWN_INTERFACE )
- skb->src_vif = VIF_PHYSICAL_INTERFACE;
-
- if ( skb->dst_vif == VIF_UNKNOWN_INTERFACE )
- skb->dst_vif = __net_get_target_vif(skb->data, skb->len, skb->src_vif);
+ if ( skb->dst_vif == NULL )
+ skb->dst_vif = net_get_target_vif(skb->data, skb->len, skb->src_vif);
- read_lock(&sys_vif_lock);
- if ( (skb->dst_vif <= VIF_PHYSICAL_INTERFACE) ||
- ((vif = sys_vif_list[skb->dst_vif]) == NULL) )
+ if ( (skb->dst_vif == VIF_PHYS) || (skb->dst_vif == VIF_DROP) )
{
- read_unlock(&sys_vif_lock);
netdev_rx_stat[this_cpu].dropped++;
unmap_domain_mem(skb->head);
kfree_skb(skb);
return NET_RX_DROP;
}
- get_vif(vif);
- read_unlock(&sys_vif_lock);
- deliver_packet(skb, vif);
- put_vif(vif);
+ deliver_packet(skb, skb->dst_vif);
+ put_vif(skb->dst_vif);
unmap_domain_mem(skb->head);
kfree_skb(skb);
static void tx_skb_release(struct sk_buff *skb)
{
int i;
- net_vif_t *vif = sys_vif_list[skb->src_vif];
+ net_vif_t *vif = skb->src_vif;
tx_shadow_entry_t *tx;
unsigned long flags;
skb->end = skb->tail = skb->head + PKT_PROT_LEN;
skb->dev = the_dev;
- skb->src_vif = vif->id;
- skb->dst_vif = VIF_PHYSICAL_INTERFACE;
+ skb->src_vif = vif;
+ skb->dst_vif = NULL;
skb->mac.raw = skb->data;
skb_shinfo(skb)->frags[0].page = frame_table +
unsigned long pte_pfn, buf_pfn;
struct pfn_info *pte_page, *buf_page;
unsigned long *ptep;
- int target;
+ net_vif_t *target;
u8 *g_data;
unsigned short protocol;
(((vif->tx_resp_prod-i) & (TX_RING_SIZE-1)) != 1);
i = TX_RING_INC(i) )
{
- tx = shared_rings->tx_ring[i].req;
+ tx = shared_rings->tx_ring[i].req;
+ target = VIF_DROP;
if ( (tx.size < PKT_PROT_LEN) || (tx.size > ETH_FRAME_LEN) )
{
goto tx_unmap_and_continue;
}
- target = __net_get_target_vif(g_data, tx.size, vif->id);
+ target = net_get_target_vif(g_data, tx.size, vif);
- if ( target > VIF_PHYSICAL_INTERFACE )
+ if ( target == VIF_PHYS )
+ {
+ vif->tx_shadow_ring[j].id = tx.id;
+ vif->tx_shadow_ring[j].size = tx.size;
+ vif->tx_shadow_ring[j].header =
+ kmem_cache_alloc(net_header_cachep, GFP_KERNEL);
+ if ( vif->tx_shadow_ring[j].header == NULL )
+ {
+ make_tx_response(vif, tx.id, RING_STATUS_OK);
+ goto tx_unmap_and_continue;
+ }
+
+ memcpy(vif->tx_shadow_ring[j].header, g_data, PKT_PROT_LEN);
+ vif->tx_shadow_ring[j].payload = tx.addr + PKT_PROT_LEN;
+ get_page_tot(buf_page);
+ j = TX_RING_INC(j);
+ }
+ else if ( target != VIF_DROP )
{
/* Local delivery */
if ( (skb = dev_alloc_skb(ETH_FRAME_LEN + 32)) == NULL )
{
make_tx_response(vif, tx.id, RING_STATUS_BAD_PAGE);
+ put_vif(target);
goto tx_unmap_and_continue;
}
- skb->src_vif = vif->id;
+ skb->src_vif = vif;
skb->dst_vif = target;
skb->protocol = protocol;
make_tx_response(vif, tx.id, RING_STATUS_OK);
}
- else if ( target == VIF_PHYSICAL_INTERFACE )
- {
- vif->tx_shadow_ring[j].id = tx.id;
- vif->tx_shadow_ring[j].size = tx.size;
- vif->tx_shadow_ring[j].header =
- kmem_cache_alloc(net_header_cachep, GFP_KERNEL);
- if ( vif->tx_shadow_ring[j].header == NULL )
- {
- make_tx_response(vif, tx.id, RING_STATUS_OK);
- goto tx_unmap_and_continue;
- }
-
- memcpy(vif->tx_shadow_ring[j].header, g_data, PKT_PROT_LEN);
- vif->tx_shadow_ring[j].payload = tx.addr + PKT_PROT_LEN;
- get_page_tot(buf_page);
- j = TX_RING_INC(j);
- }
tx_unmap_and_continue:
unmap_domain_mem(g_data);
/* Set up other state */
skb->len = 0;
skb->data_len = 0;
- skb->src_vif = VIF_UNKNOWN_INTERFACE;
- skb->dst_vif = VIF_UNKNOWN_INTERFACE;
skb->skb_type = SKB_NORMAL;
skb_shinfo(skb)->nr_frags = 0;
/* Set up other state */
skb->len = 0;
skb->data_len = 0;
- skb->src_vif = VIF_UNKNOWN_INTERFACE;
- skb->dst_vif = VIF_UNKNOWN_INTERFACE;
skb->skb_type = SKB_ZERO_COPY;
skb_shinfo(skb)->nr_frags = 0;
{
struct sk_buff *skb = p;
+ skb->src_vif = NULL;
+ skb->dst_vif = NULL;
skb->next = NULL;
skb->prev = NULL;
skb->list = NULL;
static ssize_t dom_vif_read(struct file * file, char * buff, size_t size, loff_t * off)
{
- char hyp_buf[128]; // Hypervisor is going to write its reply here.
+ char hyp_buf[128];
network_op_t op;
static int finished = 0;
- // This seems to be the only way to make the OS stop making read requests
- // to the file. When we use the fileoperations version of read, offset
- // seems to be ignored altogether.
-
- if (finished)
+ if ( finished )
{
finished = 0;
return 0;
int anton(const char *buff, int len);
static int vfr_read_proc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+ int count, int *eof, void *data)
{
strcpy(page, readbuf);
*readbuf = '\0';
((_x)=='\f') || ((_x)=='\r') || ((_x)=='\n') )
static int vfr_write_proc(struct file *file, const char *buffer,
- u_long count, void *data)
+ u_long count, void *data)
{
- network_op_t op;
- int ret, len;
- int ts, te, tl; // token start, end, and length
- int fs, fe, fl; // field.
-
- len = count;
- ts = te = 0;
-
- memset(&op, 0, sizeof(network_op_t));
-
- // get the command:
- while ( count && isspace(buffer[ts]) ) { ts++; count--; } // skip spaces.
- te = ts;
- while ( count && !isspace(buffer[te]) ) { te++; count--; } // command end
- if ( te <= ts ) goto bad;
- tl = te - ts;
-
- if ( strncmp(&buffer[ts], "ADD", tl) == 0 )
- {
- op.cmd = NETWORK_OP_ADDRULE;
- }
- else if ( strncmp(&buffer[ts], "DELETE", tl) == 0 )
- {
- op.cmd = NETWORK_OP_DELETERULE;
- }
- else if ( strncmp(&buffer[ts], "PRINT", tl) == 0 )
- {
- op.cmd = NETWORK_OP_GETRULELIST;
- goto doneparsing;
- }
-
- ts = te;
-
- // get the action
- while ( count && (buffer[ts] == ' ') ) { ts++; count--; } // skip spaces.
- te = ts;
- while ( count && (buffer[te] != ' ') ) { te++; count--; } // command end
- if ( te <= ts ) goto bad;
- tl = te - ts;
-
- if ( strncmp(&buffer[ts], "ACCEPT", tl) == 0 )
- {
- op.u.net_rule.action = NETWORK_ACTION_ACCEPT;
- goto keyval;
- }
- if ( strncmp(&buffer[ts], "COUNT", tl) == 0 )
- {
- op.u.net_rule.action = NETWORK_ACTION_COUNT;
- goto keyval;
- }
-
- // default case;
- return (len);
-
+ network_op_t op;
+ int ret, len;
+ int ts, te, tl; // token start, end, and length
+ int fs, fe, fl; // field.
- // get the key=val pairs.
- keyval:
- while (count)
- {
- //get field
- ts = te; while ( count && isspace(buffer[ts]) ) { ts++; count--; }
- te = ts;
- while ( count && !isspace(buffer[te]) && (buffer[te] != '=') )
- { te++; count--; }
- if ( te <= ts )
- goto doneparsing;
- tl = te - ts;
- fs = ts; fe = te; fl = tl; // save the field markers.
- // skip " = " (ignores extra equals.)
- while ( count && (isspace(buffer[te]) || (buffer[te] == '=')) )
- { te++; count--; }
- ts = te;
- while ( count && !isspace(buffer[te]) ) { te++; count--; }
- tl = te - ts;
+ len = count;
+ ts = te = 0;
- if ( (fl <= 0) || (tl <= 0) ) goto bad;
+ memset(&op, 0, sizeof(network_op_t));
- if (strncmp(&buffer[fs], "srcaddr", fl) == 0)
- {
- op.u.net_rule.src_addr = getipaddr(&buffer[ts], tl);
- }
- else if (strncmp(&buffer[fs], "dstaddr", fl) == 0)
- {
- op.u.net_rule.dst_addr = getipaddr(&buffer[ts], tl);
- }
- else if (strncmp(&buffer[fs], "srcaddrmask", fl) == 0)
- {
- op.u.net_rule.src_addr_mask = getipaddr(&buffer[ts], tl);
- }
- else if (strncmp(&buffer[fs], "dstaddrmask", fl) == 0)
- {
- op.u.net_rule.dst_addr_mask = getipaddr(&buffer[ts], tl);
- }
- else if (strncmp(&buffer[fs], "srcport", fl) == 0)
+ // get the command:
+ while ( count && isspace(buffer[ts]) ) { ts++; count--; } // skip spaces.
+ te = ts;
+ while ( count && !isspace(buffer[te]) ) { te++; count--; } // command end
+ if ( te <= ts ) goto bad;
+ tl = te - ts;
+
+ if ( strncmp(&buffer[ts], "ADD", tl) == 0 )
{
- op.u.net_rule.src_port = antous(&buffer[ts], tl);
+ op.cmd = NETWORK_OP_ADDRULE;
}
- else if (strncmp(&buffer[fs], "dstport", fl) == 0)
+ else if ( strncmp(&buffer[ts], "DELETE", tl) == 0 )
{
- op.u.net_rule.dst_port = antous(&buffer[ts], tl);
+ op.cmd = NETWORK_OP_DELETERULE;
}
- else if (strncmp(&buffer[fs], "srcportmask", fl) == 0)
+ else if ( strncmp(&buffer[ts], "PRINT", tl) == 0 )
{
- op.u.net_rule.src_port_mask = antous(&buffer[ts], tl);
+ op.cmd = NETWORK_OP_GETRULELIST;
+ goto doneparsing;
}
- else if (strncmp(&buffer[fs], "dstportmask", fl) == 0)
+
+ ts = te;
+
+ // get the action
+ while ( count && (buffer[ts] == ' ') ) { ts++; count--; } // skip spaces.
+ te = ts;
+ while ( count && (buffer[te] != ' ') ) { te++; count--; } // command end
+ if ( te <= ts ) goto bad;
+ tl = te - ts;
+
+ if ( strncmp(&buffer[ts], "ACCEPT", tl) == 0 )
{
- op.u.net_rule.dst_port_mask = antous(&buffer[ts], tl);
+ op.u.net_rule.action = NETWORK_ACTION_ACCEPT;
+ goto keyval;
}
- else if (strncmp(&buffer[fs], "srcint", fl) == 0)
+ if ( strncmp(&buffer[ts], "COUNT", tl) == 0 )
{
- op.u.net_rule.src_interface = anton(&buffer[ts], tl);
+ op.u.net_rule.action = NETWORK_ACTION_COUNT;
+ goto keyval;
}
- else if (strncmp(&buffer[fs], "dstint", fl) == 0)
+
+ // default case;
+ return (len);
+
+
+ // get the key=val pairs.
+ keyval:
+ while (count)
{
- op.u.net_rule.dst_interface = anton(&buffer[ts], tl);
- }
- else if ( (strncmp(&buffer[fs], "proto", fl) == 0))
- {
- if (strncmp(&buffer[ts], "any", tl) == 0)
- op.u.net_rule.proto = NETWORK_PROTO_ANY;
- if (strncmp(&buffer[ts], "ip", tl) == 0)
- op.u.net_rule.proto = NETWORK_PROTO_IP;
- if (strncmp(&buffer[ts], "tcp", tl) == 0)
- op.u.net_rule.proto = NETWORK_PROTO_TCP;
- if (strncmp(&buffer[ts], "udp", tl) == 0)
- op.u.net_rule.proto = NETWORK_PROTO_UDP;
- if (strncmp(&buffer[ts], "arp", tl) == 0)
- op.u.net_rule.proto = NETWORK_PROTO_ARP;
-
+ //get field
+ ts = te; while ( count && isspace(buffer[ts]) ) { ts++; count--; }
+ te = ts;
+ while ( count && !isspace(buffer[te]) && (buffer[te] != '=') )
+ { te++; count--; }
+ if ( te <= ts )
+ goto doneparsing;
+ tl = te - ts;
+ fs = ts; fe = te; fl = tl; // save the field markers.
+ // skip " = " (ignores extra equals.)
+ while ( count && (isspace(buffer[te]) || (buffer[te] == '=')) )
+ { te++; count--; }
+ ts = te;
+ while ( count && !isspace(buffer[te]) ) { te++; count--; }
+ tl = te - ts;
+
+ if ( (fl <= 0) || (tl <= 0) ) goto bad;
+
+ /* NB. Prefix matches must go first! */
+ if (strncmp(&buffer[fs], "src", fl) == 0)
+ {
+ op.u.net_rule.src_vif = VIF_ANY_INTERFACE;
+ }
+ else if (strncmp(&buffer[fs], "dst", fl) == 0)
+ {
+ op.u.net_rule.dst_vif = VIF_PHYSICAL_INTERFACE;
+ }
+ else if (strncmp(&buffer[fs], "srcaddr", fl) == 0)
+ {
+ op.u.net_rule.src_addr = getipaddr(&buffer[ts], tl);
+ }
+ else if (strncmp(&buffer[fs], "dstaddr", fl) == 0)
+ {
+ op.u.net_rule.dst_addr = getipaddr(&buffer[ts], tl);
+ }
+ else if (strncmp(&buffer[fs], "srcaddrmask", fl) == 0)
+ {
+ op.u.net_rule.src_addr_mask = getipaddr(&buffer[ts], tl);
+ }
+ else if (strncmp(&buffer[fs], "dstaddrmask", fl) == 0)
+ {
+ op.u.net_rule.dst_addr_mask = getipaddr(&buffer[ts], tl);
+ }
+ else if (strncmp(&buffer[fs], "srcport", fl) == 0)
+ {
+ op.u.net_rule.src_port = antous(&buffer[ts], tl);
+ }
+ else if (strncmp(&buffer[fs], "dstport", fl) == 0)
+ {
+ op.u.net_rule.dst_port = antous(&buffer[ts], tl);
+ }
+ else if (strncmp(&buffer[fs], "srcportmask", fl) == 0)
+ {
+ op.u.net_rule.src_port_mask = antous(&buffer[ts], tl);
+ }
+ else if (strncmp(&buffer[fs], "dstportmask", fl) == 0)
+ {
+ op.u.net_rule.dst_port_mask = antous(&buffer[ts], tl);
+ }
+ else if (strncmp(&buffer[fs], "srcdom", fl) == 0)
+ {
+ op.u.net_rule.src_vif |= anton(&buffer[ts], tl)<<VIF_DOMAIN_SHIFT;
+ }
+ else if (strncmp(&buffer[fs], "srcidx", fl) == 0)
+ {
+ op.u.net_rule.src_vif |= anton(&buffer[ts], tl);
+ }
+ else if (strncmp(&buffer[fs], "dstdom", fl) == 0)
+ {
+ op.u.net_rule.dst_vif |= anton(&buffer[ts], tl)<<VIF_DOMAIN_SHIFT;
+ }
+ else if (strncmp(&buffer[fs], "dstidx", fl) == 0)
+ {
+ op.u.net_rule.dst_vif |= anton(&buffer[ts], tl);
+ }
+ else if ( (strncmp(&buffer[fs], "proto", fl) == 0))
+ {
+ if (strncmp(&buffer[ts], "any", tl) == 0)
+ op.u.net_rule.proto = NETWORK_PROTO_ANY;
+ if (strncmp(&buffer[ts], "ip", tl) == 0)
+ op.u.net_rule.proto = NETWORK_PROTO_IP;
+ if (strncmp(&buffer[ts], "tcp", tl) == 0)
+ op.u.net_rule.proto = NETWORK_PROTO_TCP;
+ if (strncmp(&buffer[ts], "udp", tl) == 0)
+ op.u.net_rule.proto = NETWORK_PROTO_UDP;
+ if (strncmp(&buffer[ts], "arp", tl) == 0)
+ op.u.net_rule.proto = NETWORK_PROTO_ARP;
+ }
}
- }
doneparsing:
- ret = HYPERVISOR_network_op(&op);
- return(len);
+ ret = HYPERVISOR_network_op(&op);
+ return(len);
bad:
- return(len);
+ return(len);
}
u16 antous(const char *buff, int len)
{
- u16 ret;
- char c;
+ u16 ret;
+ char c;
- ret = 0;
+ ret = 0;
- while ( (len) && ((c = *buff) >= '0') && (c <= '9') )
- {
- ret *= 10;
- ret += c - '0';
- buff++; len--;
- }
+ while ( (len) && ((c = *buff) >= '0') && (c <= '9') )
+ {
+ ret *= 10;
+ ret += c - '0';
+ buff++; len--;
+ }
- return ret;
+ return ret;
}
u32 getipaddr(const char *buff, unsigned int len)
{
- int i;
- char c;
- u32 ret, val;
+ char c;
+ u32 ret, val;
- ret = 0; val = 0;
+ ret = 0; val = 0;
- while ( len )
- {
- if (!((((c = *buff) >= '0') && ( c <= '9')) || ( c == '.' ) ) )
+ while ( len )
{
- return(0); // malformed.
+ if (!((((c = *buff) >= '0') && ( c <= '9')) || ( c == '.' ) ) )
+ {
+ return(0); // malformed.
+ }
+
+ if ( c == '.' ) {
+ if (val > 255) return (0); //malformed.
+ ret = ret << 8;
+ ret += val;
+ val = 0;
+ len--; buff++;
+ continue;
+ }
+ val *= 10;
+ val += c - '0';
+ buff++; len--;
}
+ ret = ret << 8;
+ ret += val;
- if ( c == '.' ) {
- if (val > 255) return (0); //malformed.
- ret = ret << 8;
- ret += val;
- val = 0;
- len--; buff++;
- continue;
- }
- val *= 10;
- val += c - '0';
- buff++; len--;
- }
- ret = ret << 8;
- ret += val;
-
- return (ret);
+ return (ret);
}